package com.ltu.timkor6.gamesite.games.missingbits.client;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.ltu.timkor6.gamesite.games.missingbits.shared.Question;
import com.ltu.timkor6.gamesite.shared.CompositeAbstract;
import com.ltu.timkor6.gamesite.shared.Result;

public class MissingBitsComposite extends CompositeAbstract
{
	private static final String CSS_MISSING_TABLE = "missing-table";
	private static final String CSS_MISSING_QUESTION = "missing-question";
	private static final String CSS_MISSING_ANSWER = "missing-answer";
	private static final String CSS_MISSING_FINISHED = "missing-finished";
	
	private MissingBits missingBits;
	private SimplePanel info;
	private SimplePanel content;
	
	private VerticalPanel infoPanel = new VerticalPanel();
	private VerticalPanel game;
	private HorizontalPanel answer;
	
	private int questionNumber = 0;
	private int numberOfGames = 0;
	private int points = 0;
	
	private int gameTime = 0;
	private int questionTime = 0;
	
	private TextBox number;
	private TextBox textAnswer;
	private Label labelQuestions;
	private Label labelPoints;
	private Label labelGameTime;
	private Label labelQuestionTime;
	
	private Timer t;
	
	public MissingBitsComposite(MissingBits missingBits)
	{
		this.missingBits = missingBits;
		
		// Title
		final Label title = new Label("Missing Bits");
		title.setStyleName("panelHeader");
		panel.add(title);
		
		info = new SimplePanel();
		info.setStyleName("game-info");
		content = new SimplePanel();
		content.setStyleName("game-playarea");
		
		panel.add(info);
		panel.add(content);
		
		loadModule();
		
		initWidget(panel);
	}
	
	/**
	 * Set up the game.
	 */
	public void loadModule()
	{
		this.info.setStyleName("errors");
		VerticalPanel startPanel = new VerticalPanel();
		
		Label label = new Label("Number of questions");
		
		number = new TextBox();
		number.setText("5");
		number.addKeyPressHandler(new KeyPressHandler()
		{
			public void onKeyPress(KeyPressEvent event)
			{
				if(event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER)
				{
					missingBits.checkSubmit();
				}
			}
		});
		
		Button submit = new Button("Start!");
		submit.addClickHandler(new ClickHandler()
		{
			public void onClick(ClickEvent event) {
				missingBits.checkSubmit();
			}
		});
		
		startPanel.add(label);
		startPanel.add(number);
		startPanel.add(submit);
		
		content.setWidget(startPanel);
	}
	
	public String getNumber()
	{
		return this.number.getText();
	}
	
	public void addError(String error)
	{
		this.info.setWidget(new Label(error));
	}

	public void setElements(int questions)
	{
		this.numberOfGames = questions;
	}
	
	/**
	 * Each question.
	 * @param question
	 */
	public void question(Question question)
	{
		// Info panel
		this.infoPanel.clear();
		this.info.setWidget(infoPanel);
		this.info.setStyleName("game-info");
		
		this.questionNumber++;
		this.questionTime = 0;
		
		labelQuestions = new Label("Question " + question.getQuestionNumber() + " of " + numberOfGames);
		labelPoints = new Label("Points: " + this.points);
		labelGameTime = new Label("Game time: " + formatTime(this.gameTime));
		labelQuestionTime = new Label("Question time: " + formatTime(this.questionTime));
		
		infoPanel.add(labelQuestions);
		infoPanel.add(labelPoints);
		infoPanel.add(labelGameTime);
		infoPanel.add(labelQuestionTime);
		
		
		// The game
		this.game = new VerticalPanel();
		this.game.setStyleName(CSS_MISSING_TABLE);
		
		expression(question);
		
		this.answer = new HorizontalPanel();
		this.answer.setStyleName(CSS_MISSING_ANSWER);
		
		this.textAnswer = new TextBox();
		this.textAnswer.addKeyPressHandler(new KeyPressHandler()
		{
			public void onKeyPress(KeyPressEvent event)
			{
				if(event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER)
				{
					answer();
				}
			}
		});
		Button submit = new Button("Answer");
		submit.addClickHandler(new ClickHandler()
		{
			public void onClick(ClickEvent event)
			{
				answer();
			}
		});
		
		this.answer.add(textAnswer);
		this.answer.add(submit);
		
		this.game.add(answer);
		
		this.textAnswer.setFocus(true);
		
		checkTime(1000);
		
		this.content.setWidget(game);
	}
	
	private void expression(Question question)
	{
		HorizontalPanel expression = new HorizontalPanel();
		expression.setStyleName(CSS_MISSING_QUESTION);
		
		expression.add(new Label(String.valueOf(question.getFirst())));
		expression.add(new Label(String.valueOf(question.getSign())));
		expression.add(new Label(String.valueOf(question.getSecond())));
		expression.add(new Label("="));
		expression.add(new Label("?"));
		
		game.add(expression);
	}
	
	/**
	 * Send a answer back to server.
	 */
	private void answer()
	{
		String answer = this.textAnswer.getText().trim();
		this.missingBits.sendAnswer(answer);
	}
	
	/**
	 * Next question screen.
	 * @param points
	 */
	public void showNextQuestion(int points)
	{
		answer.clear();
		t.cancel();
		
		updatePoints(points);
		
		String status = (0 < points) ? "Correct" : "Wrong answer" ;
		Label labelStatus = new Label(status);
		answer.add(labelStatus);
		
		if(questionNumber == numberOfGames)
		{
			Button submit = new Button("Finished");
			submit.addClickHandler(new ClickHandler()
			{
				public void onClick(ClickEvent event)
				{
					missingBits.getResult();
				}
			});
			answer.add(submit);
			
			submit.setFocus(true);
		}
		else
		{
			Button submit = new Button("Next question");
			submit.addClickHandler(new ClickHandler()
			{
				public void onClick(ClickEvent event)
				{
					missingBits.getQuestion();
				}
			});
			answer.add(submit);
			
			submit.setFocus(true);
		}
	}
	
	public void showResult(Result result)
	{
		this.game.clear();
		t.cancel();
		
		Label finished = new Label("Finished with " + result.getPoints() + " points.");
		finished.setStyleName(CSS_MISSING_FINISHED);
		this.game.add(finished);
		
		answer.clear();
	}
	
	private void updatePoints(int addPoints)
	{
		this.points += addPoints;
		this.labelPoints.setText("Points: " + points);
	}
	
	private String formatTime(int seconds)
	{
		int intMinutes = seconds / 60;
		int intSeconds = seconds % 60;
		
		String stringMinutes = NumberFormat.getFormat("00").format(intMinutes);
		String stringSeconds = NumberFormat.getFormat("00").format(intSeconds);
		
		return stringMinutes + ":" + stringSeconds;
	}
	
	private void checkTime(int time)
	{
		t = new Timer()
		{
			public void run()
			{
				labelGameTime.setText("Game time: " + formatTime(gameTime));
				labelQuestionTime.setText("Question time: " + formatTime(questionTime));
				
				gameTime++;
				questionTime++;
			}
		};
		
		t.scheduleRepeating(time);
	}
}
